package com.enation.app.javashop.core.goodssearch.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.enation.app.javashop.core.client.goods.GoodsClient;
import com.enation.app.javashop.core.client.goods.GoodsWordsClient;
import com.enation.app.javashop.core.client.member.ShopCatClient;
import com.enation.app.javashop.core.goods.model.dos.CategoryDO;
import com.enation.app.javashop.core.goods.service.CategoryManager;
import com.enation.app.javashop.core.goodssearch.model.GoodsIndex;
import com.enation.app.javashop.core.goodssearch.model.Param;
import com.enation.app.javashop.core.goodssearch.service.GoodsIndexManager;
import com.enation.app.javashop.core.goodssearch.util.HexUtil;
import com.enation.app.javashop.core.shop.model.dos.ShopCatDO;
import com.enation.app.javashop.core.system.progress.model.TaskProgress;
import com.enation.app.javashop.core.system.progress.model.TaskProgressConstant;
import com.enation.app.javashop.core.system.progress.service.ProgressManager;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse.AnalyzeToken;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.transport.TransportClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.stereotype.Service;


/**
 * es的商品索引实现
 *
 * @author fk
 * @version v6.4
 * @since v6.4
 * 2017年9月18日 上午11:41:44
 */
@Service
public class GoodsIndexManagerImpl implements GoodsIndexManager {

    @Autowired
    private TransportClient client;
    @Autowired
    private GoodsClient goodsClient;
    @Autowired
    private ShopCatClient shopCatClient;
    @Autowired
    private ProgressManager progressManager;
    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    public final static String INDEXNAME = "javashop";

    public final static String TYPE = "goods";

    protected final Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    private GoodsWordsClient goodsWordsClient;


    public GoodsIndexManagerImpl() {
        System.out.println("init in impl");
        System.setProperty("es.set.netty.runtime.available.processors", "false");
    }

    @Override
    public void addIndex(Map goods) {

        //创建索引
        if (!elasticsearchOperations.indexExists(INDEXNAME)) {
            elasticsearchOperations.createIndex(INDEXNAME);
            //指定Mapping
            elasticsearchOperations.putMapping(GoodsIndex.class);
        }


        GoodsIndex goodsIndex = this.getSource(goods);

        IndexQuery indexQuery = new IndexQuery();
        indexQuery.setIndexName(INDEXNAME);
        indexQuery.setType(TYPE);
        indexQuery.setId(goodsIndex.getGoodsId().toString());
        indexQuery.setObject(goodsIndex);

        //审核通过且没有下架且没有删除
        boolean flag = goodsIndex.getDisabled() == 1 && goodsIndex.getMarketEnable() == 1 && goodsIndex.getIsAuth() == 1;
        if (flag) {
            String goodsName = goods.get("goods_name").toString();

            List<String> wordsList = toWordsList(goodsName);

            // 分词入库
            this.wordsToDb(wordsList);
        }

        elasticsearchOperations.index(indexQuery);
    }

    @Override
    public void updateIndex(Map goods) {

        //删除
        this.deleteIndex(goods);
        //添加
        this.addIndex(goods);

    }

    @Override
    public void deleteIndex(Map goods) {


        elasticsearchOperations.delete(INDEXNAME, TYPE, goods.get("goods_id").toString());

        String goodsName = goods.get("goods_name").toString();
        List<String> wordsList = toWordsList(goodsName);
        this.deleteWords(wordsList);

    }

    /**
     * 将list中的分词减一
     *
     * @param wordsList
     */
    private void deleteWords(List<String> wordsList) {
        for (String words : wordsList) {
            this.goodsWordsClient.delete(words);
        }
    }

    /**
     * 封装成内存需要格式数据
     *
     * @param goods
     * @return
     */
    private GoodsIndex getSource(Map goods) {

        GoodsIndex goodsIndex = new GoodsIndex();
        goodsIndex.setGoodsId(StringUtil.toInt(goods.get("goods_id").toString(), 0));
        goodsIndex.setGoodsName(goods.get("goods_name").toString());
        goodsIndex.setThumbnail(goods.get("thumbnail") == null ? "" : goods.get("thumbnail").toString());
        goodsIndex.setSmall(goods.get("small") == null ? "" : goods.get("small").toString());
        Double p = goods.get("price") == null ? 0d : StringUtil.toDouble(goods.get("price").toString(), 0d);
        goodsIndex.setPrice(p);
        goodsIndex.setBuyCount(goods.get("buy_count") == null ? 0 : StringUtil.toInt(goods.get("buy_count").toString(), 0));
        goodsIndex.setSellerId(StringUtil.toInt(goods.get("seller_id").toString(), 0));
        //店铺分组
        goodsIndex.setShopCatId(goods.get("shop_cat_id") == null ? 0 : StringUtil.toInt(goods.get("shop_cat_id").toString(), 0));
        goodsIndex.setShopCatPath("");
        if (goodsIndex.getShopCatId() != 0) {
            ShopCatDO shopCat = shopCatClient.getModel(goodsIndex.getShopCatId());
            if (shopCat != null) {
                goodsIndex.setShopCatPath(HexUtil.encode(shopCat.getCatPath()));
            }
        }

        goodsIndex.setSellerName(goods.get("seller_name").toString());
        goodsIndex.setCommentNum(goods.get("comment_num") == null ? 0 : StringUtil.toInt(goods.get("comment_num").toString(), 0));
        goodsIndex.setGrade(goods.get("grade") == null ? 100 : StringUtil.toDouble(goods.get("grade").toString(), 100d));

        goodsIndex.setBrand(goods.get("brand_id") == null ? 0 : StringUtil.toInt(goods.get("brand_id").toString(), 0));
        goodsIndex.setCategoryId(goods.get("category_id") == null ? 0 : StringUtil.toInt(goods.get("category_id").toString(), 0));
        CategoryDO cat = goodsClient.getModel(Integer.parseInt(goods.get("category_id").toString()));
        goodsIndex.setCategoryPath(HexUtil.encode(cat.getCategoryPath()));
        goodsIndex.setDisabled(StringUtil.toInt(goods.get("disabled").toString(), 0));
        goodsIndex.setMarketEnable(StringUtil.toInt(goods.get("market_enable").toString(), 0));
        goodsIndex.setIsAuth(StringUtil.toInt(goods.get("is_auth").toString(), 0));
        goodsIndex.setIntro(goods.get("intro") == null ? "" : goods.get("intro").toString());
        goodsIndex.setSelfOperated(goods.get("self_operated") == null ? 0 : StringUtil.toInt(goods.get("self_operated").toString(), 0));

        //参数维度,已填写参数
        List<Map> params = (List<Map>) goods.get("params");
        List<Param> paramsList = this.convertParam(params);
        goodsIndex.setParams(paramsList);

        return goodsIndex;
    }

    /**
     * 获取分词结果
     *
     * @param txt
     * @return 分词list
     */
    private List<String> toWordsList(String txt) {

        List<String> list = new ArrayList<String>();
        IndicesAdminClient indicesAdminClient = client.admin().indices();
        AnalyzeRequestBuilder request = new AnalyzeRequestBuilder(indicesAdminClient, AnalyzeAction.INSTANCE, INDEXNAME, txt);
        //	分词
        request.setAnalyzer("ik_max_word");
        request.setTokenizer("ik_max_word");
        List<AnalyzeToken> listAnalysis = request.execute().actionGet().getTokens();
        for (AnalyzeToken token : listAnalysis) {
            list.add(token.getTerm());
        }
        return list;
    }

    /**
     * 转换参数
     *
     * @param params
     * @return
     */
    private List<Param> convertParam(List<Map> params) {
        List<Param> paramIndices = new ArrayList<>();
        if (params != null && params.size() > 0) {

            for (Map param : params) {
                Param index = new Param();
                index.setName(param.get("param_name") == null ? "" : param.get("param_name").toString());
                index.setValue(param.get("param_value") == null ? "" : param.get("param_value").toString());
                paramIndices.add(index);
            }

        }
        return paramIndices;
    }


    /**
     * 将分词结果写入数据库
     *
     * @param wordsList
     */
    private void wordsToDb(List<String> wordsList) {

        for (String words : wordsList) {

            goodsWordsClient.addWords(words);
        }
    }

    @Override
    public void addAll(List<Map<String, Object>> list, int index) {
        //删除所有的索引
        if (index == 1) {
            if (elasticsearchOperations.indexExists(INDEXNAME)) {
                elasticsearchOperations.deleteIndex(INDEXNAME);
                goodsWordsClient.delete();
            }
        }
        //循环生成索引
        for (Map goods : list) {
            /** 生成索引消息 */
            this.showMessage(StringUtil.toString(goods.get("goods_name")));
            /** 生成索引之 */
            this.addIndex(goods);
        }
    }

    /**
     * 生成消息
     *
     * @param goodsName 商品名称
     */
    private void showMessage(String goodsName) {
        try {
            TaskProgress tk = progressManager.getProgress(TaskProgressConstant.GOODS_INDEX);
            tk.step("正在生成[" + goodsName + "]");
            progressManager.putProgress(TaskProgressConstant.GOODS_INDEX, tk);
        } catch (Exception e) {
            logger.error(e);
        }
    }

}
